structure E = AsmErrorMsg

type pos = int

type svalue = Tokens.svalue
type ('a,'b) token = ('a,'b) Tokens.token
type lexresult  = (svalue, pos) token

val lineNum = E.lineNum
val linePos = E.linePos
  
val eof = (fn () => let val pos = List.hd(!linePos)
                    in  Tokens.EOF(pos, pos)
                    end)

%%

%header (functor x86LexFun(structure Tokens : x86_TOKENS));
%s COMMENT ASSERT;
al=[\._0-9a-zA-Z];
digit=[0-9];
signed="-"digit+;
ws=[\ \t];

%%
<INITIAL>{ws}+ 	        => (continue());
<INITIAL>\.text         => (Tokens.TEXT(yypos, yypos + size yytext));
<INITIAL>\.align        => (Tokens.ALIGN(yypos, yypos + size yytext));
<INITIAL>\.globl        => (Tokens.GLOBL(yypos, yypos + size yytext));
<INITIAL>\.data         => (Tokens.DATA(yypos, yypos + size yytext));
<INITIAL>\.long         => (Tokens.LONG(yypos, yypos + size yytext));
<INITIAL>\.rept         => (Tokens.REPT(yypos, yypos + size yytext));
<INITIAL>\.endr         => (Tokens.ENDR(yypos, yypos + size yytext));


<INITIAL>"-"            => (Tokens.MINUS(yypos, yypos + size yytext));
<INITIAL>","            => (Tokens.COMMA(yypos, yypos + size yytext));
<INITIAL>"("            => (Tokens.LPAREN(yypos, yypos + size yytext));
<INITIAL>")"            => (Tokens.RPAREN(yypos, yypos + size yytext));
<INITIAL>":"            => (Tokens.COLON(yypos, yypos + size yytext));
<INITIAL>"$"            => (Tokens.DOLLAR(yypos, yypos + size yytext));

<INITIAL>%eax           => (Tokens.EAX (yypos, yypos + size yytext));
<INITIAL>%ebx           => (Tokens.EBX (yypos, yypos + size yytext));
<INITIAL>%ecx           => (Tokens.ECX (yypos, yypos + size yytext));
<INITIAL>%edx           => (Tokens.EDX (yypos, yypos + size yytext));
<INITIAL>%edi           => (Tokens.EDI (yypos, yypos + size yytext));
<INITIAL>%esi           => (Tokens.ESI (yypos, yypos + size yytext));
<INITIAL>%ebp           => (Tokens.EBP (yypos, yypos + size yytext));
<INITIAL>%esp           => (Tokens.ESP (yypos, yypos + size yytext));


<INITIAL>addl           => (Tokens.ADDL (yypos, yypos + size yytext));
<INITIAL>call           => (Tokens.CALL (yypos, yypos + size yytext));
<INITIAL>cltd           => (Tokens.CLTD (yypos, yypos + size yytext));
<INITIAL>cmpl           => (Tokens.CMPL (yypos, yypos + size yytext));
<INITIAL>free           => (Tokens.FREE (yypos, yypos + size yytext));
<INITIAL>idivl          => (Tokens.IDIVL (yypos, yypos + size yytext));
<INITIAL>imull          => (Tokens.IMULL (yypos, yypos + size yytext));
<INITIAL>je             => (Tokens.JE (yypos, yypos + size yytext));
<INITIAL>jg             => (Tokens.JG (yypos, yypos + size yytext));
<INITIAL>jge            => (Tokens.JGE (yypos, yypos + size yytext));
<INITIAL>jmp            => (Tokens.JMP (yypos, yypos + size yytext));
<INITIAL>leal           => (Tokens.LEAL (yypos, yypos + size yytext));
<INITIAL>leave          => (Tokens.LEAVE (yypos, yypos + size yytext));
<INITIAL>malloc         => (Tokens.MALLOC (yypos, yypos + size yytext));
<INITIAL>movl           => (Tokens.MOVL (yypos, yypos + size yytext));
<INITIAL>pushl          => (Tokens.PUSHL (yypos, yypos + size yytext));
<INITIAL>popl           => (Tokens.POPL (yypos, yypos + size yytext));
<INITIAL>ret            => (Tokens.RET (yypos, yypos + size yytext));
<INITIAL>subl           => (Tokens.SUBL (yypos, yypos + size yytext));
<INITIAL>xchg           => (Tokens.XCHG (yypos, yypos + size yytext));

<INITIAL>"#"		=> (YYBEGIN COMMENT; continue());
<COMMENT>\n		=> (YYBEGIN INITIAL; lineNum := !lineNum+1; linePos := yypos :: !linePos; continue());
<COMMENT>.		=> (continue());

<INITIAL>">="           => (Tokens.GE(yypos, yypos + size yytext));
<INITIAL>">"            => (Tokens.GT(yypos, yypos + size yytext));
<INITIAL>"<="           => (Tokens.LE(yypos, yypos + size yytext));
<INITIAL>"<"            => (Tokens.LT(yypos, yypos + size yytext));
<INITIAL>"=="           => (Tokens.EQ(yypos, yypos + size yytext));
<INITIAL>"!="           => (Tokens.NEQ(yypos, yypos + size yytext));
<INITIAL>"&&"           => (Tokens.BAND(yypos, yypos + size yytext));
<INITIAL>"||"           => (Tokens.BOR(yypos, yypos + size yytext));
<INITIAL>"!"            => (Tokens.NOT(yypos, yypos + size yytext));
<INITIAL>"="            => (Tokens.ASSIGN(yypos, yypos + size yytext));
<INITIAL>"#@"           => (YYBEGIN ASSERT; Tokens.LANNO(yypos, yypos + size yytext)); 


<ASSERT>{ws}+ 	        => (continue());
<ASSERT>":"             => (Tokens.A_COLON (yypos, yypos + size yytext));
<ASSERT>";"             => (Tokens.A_SEMICOLON (yypos, yypos + size yytext));
<ASSERT>"#"             => (continue());
<ASSERT>","             => (Tokens.A_COMMA(yypos, yypos + size yytext));
<ASSERT>"."             => (Tokens.A_DOT(yypos, yypos + size yytext));
<ASSERT>"->"            => (Tokens.A_PTR_OP(yypos, yypos + size yytext));
<ASSERT>"["             => (Tokens.A_LREGU(yypos,yypos + size yytext));
<ASSERT>"]"             => (Tokens.A_RREGU(yypos,yypos + size yytext));
<ASSERT>\n		=> (lineNum := !lineNum+1; linePos := yypos :: !linePos;continue());
<ASSERT>"("		=> (Tokens.A_LPAREN(yypos, yypos + size yytext));
<ASSERT>")"             => (Tokens.A_RPAREN(yypos, yypos + size yytext));
<ASSERT>"+"             => (Tokens.A_ADD(yypos, yypos + size yytext));
<ASSERT>"-"             => (Tokens.A_MINUS(yypos, yypos + size yytext));
<ASSERT>"*"             => (Tokens.A_MUL(yypos, yypos + size yytext));
<ASSERT>"/"             => (Tokens.A_DIV(yypos, yypos + size yytext));
<ASSERT>"%"             => (Tokens.A_MODUS(yypos, yypos + size yytext));
<ASSERT>">="            => (Tokens.A_GE(yypos,yypos + size yytext));
<ASSERT>">"             => (Tokens.A_GT(yypos,yypos + size yytext));
<ASSERT>"<="            => (Tokens.A_LE(yypos,yypos + size yytext));
<ASSERT>"<"             => (Tokens.A_LT(yypos,yypos + size yytext));
<ASSERT>"=="            => (Tokens.A_EQ(yypos,yypos + size yytext));
<ASSERT>"!="            => (Tokens.A_NEQ(yypos,yypos + size yytext));
<ASSERT>"&&"            => (Tokens.A_BAND(yypos,yypos + size yytext));
<ASSERT>"||"            => (Tokens.A_BOR(yypos,yypos + size yytext));
<ASSERT>"!"             => (Tokens.A_NOT(yypos,yypos + size yytext));
<ASSERT>"="             => (Tokens.A_ASSIGN(yypos, yypos + size yytext));
<ASSERT>%eax            => (Tokens.A_EAX(yypos, yypos + size yytext));
<ASSERT>%ebx            => (Tokens.A_EBX(yypos, yypos + size yytext));
<ASSERT>%ecx            => (Tokens.A_ECX(yypos, yypos + size yytext));
<ASSERT>%edx            => (Tokens.A_EDX(yypos, yypos + size yytext));
<ASSERT>%edi            => (Tokens.A_EDI(yypos, yypos + size yytext));
<ASSERT>%esi            => (Tokens.A_ESI(yypos, yypos + size yytext));
<ASSERT>%ebp            => (Tokens.A_EBP(yypos, yypos + size yytext));
<ASSERT>%esp            => (Tokens.A_ESP(yypos, yypos + size yytext));
<ASSERT>exists          => (Tokens.A_EXISTS(yypos, yypos + size yytext));
<ASSERT>forall          => (Tokens.A_FORALL(yypos, yypos + size yytext));
<ASSERT>int             => (Tokens.A_INT(yypos,yypos + size yytext));
<ASSERT>list            => (Tokens.A_LIST(yypos, yypos + size yytext));
<ASSERT>pre             => (Tokens.A_PRE(yypos, yypos + size yytext));
<ASSERT>post	        => (Tokens.A_POST(yypos, yypos + size yytext));
<ASSERT>struct          => (Tokens.A_STRUCT(yypos,yypos + size yytext));
<ASSERT>tree            => (Tokens.A_TREE(yypos, yypos + size yytext));
<ASSERT>true            => (Tokens.A_TRUE(yypos,yypos + size yytext));
<ASSERT>wild          	=> (Tokens.A_WILD(yypos, yypos + size yytext));
<ASSERT>Pi              => (Tokens.A_PI(yypos, yypos + size yytext));
<ASSERT>N               => (Tokens.A_N(yypos, yypos + size yytext));
<ASSERT>D           	=> (Tokens.A_D(yypos, yypos + size yytext));

<ASSERT>"{"    	        => (Tokens.A_LBRACE(yypos,yypos + size yytext));
<ASSERT>"}"    	        => (Tokens.A_RBRACE(yypos,yypos + size yytext));
<ASSERT>"<=>"           => (Tokens.A_IFF(yypos, yypos + size yytext));
<ASSERT>"=>"            => (Tokens.A_IMPLY(yypos, yypos + size yytext));
<ASSERT>[_a-zA-Z]{al}*  => (Tokens.A_ID(yytext, yypos, yypos + size yytext));
<ASSERT>-{digit}+	=> (Tokens.A_INTC(Option.valOf(Int.fromString(yytext)), yypos, yypos + size yytext));
<ASSERT>{digit}+	=> (Tokens.A_INTC(Option.valOf(Int.fromString(yytext)), yypos, yypos + size yytext));
<ASSERT>"#@"		=> (YYBEGIN INITIAL; Tokens.RANNO (yypos, yypos + size yytext));
<ASSERT>.       	=> (E.error yypos ("Invalid character in assertion: "^yytext); continue());

<INITIAL>[\._a-zA-Z]{al}* => (Tokens.ID(yytext, yypos, yypos + size yytext));
<INITIAL>-{digit}+	=> (Tokens.INTC(Option.valOf(Int.fromString(yytext)), yypos, yypos + size yytext));
<INITIAL>{digit}+	=> (Tokens.INTC(Option.valOf(Int.fromString(yytext)), yypos, yypos + size yytext));
<INITIAL>\n	=> (lineNum := !lineNum+1; linePos := yypos :: !linePos; continue());
<INITIAL>.       	=> (E.error yypos ("Invalid character: "^yytext); continue());
